In diesem Kapitel schauen wir uns die HTTP-Kommunikation etwas genauer an. Eine vom Client ankommende Anfrage (Request) an den Port 80 des Webservers landet bei dem Webserver-Prozess. Dies kann beispielsweise ein laufender Apache-Server sein. Wird beispielsweise nach der index-html Datei verlangt, so wird diese vom Dateisystem des Servers eingelesen. Dieser verpackt die HTML-Datei in eine Antwort (Response) und sendet diese zum Client zurück. GET ist dabei die gebräuchlichste Request-Methode im HTTP-Protokoll. Mit ihr wird eine Ressource (zum Beispiel eine Datei) unter Angabe eines URI vom Server angefordert. Zum Beispiel wird aus http hs-mannheim.de meineDatei.php das Kommando GET meineDatei.php auf dem Webserver HS-Mannheim. Als Argumente in dem URI können also auch Inhalte zum Server übertragen werden, allerdings soll laut Standard eine GET-Anfrage nur Daten abrufen und sonst keine Auswirkungen haben. Mögliche Auswirkungen wären beispielsweise Datenänderungen auf dem Server oder das Ausloggen. Die Länge des URIs ist je nach eingesetztem Server begrenzt und sollte aus Gründen der Abwärtskompatibilität nicht länger als 255 Bytes sein. Das Bild zeigt eine HTTP-Anfrage in Form eines GET-Requests an die Website der Hochschule Mannheim. Eine HTTP-Anfrage wird vom Browser an einen Webserver gesendet, um Ressourcen wie HTML-Dokumente, Bilder oder Dateien anzufordern. Diese Anfrage besteht aus mehreren wichtigen Komponenten, die im Bild detailliert dargestellt sind. Die erste Zeile ist die Request Line, die die Methode (GET), den Pfad und die HTTP-Version spezifiziert. Hier wird die Hauptseite der Domain [www.hs-mannheim.de](http://www.hs-mannheim.de) angefordert. Der Host gibt die Ziel-Domain des Requests an. Dies ist besonders wichtig bei virtuellen Hosts, bei denen ein Server mehrere Websites bedient. Der User-Agent identifiziert den Client, der die Anfrage sendet. In diesem Fall ein Browser, der sich als Mozilla 5.0 ausgibt. Dies kann für Server-Anpassungen basierend auf dem verwendeten Browser genutzt werden. Accept gibt an, welche Content-Types der Client akzeptiert. Hier werden HTML, XHTML, XML und alle anderen Typen mit unterschiedlichen Prioritäten (q-Werte) akzeptiert. Accept-Language gibt die bevorzugten Sprachen an, die der Client akzeptiert. Hier sind es US-Englisch mit höchster Priorität und allgemeines Englisch mit geringerer Priorität. Accept-Encoding gibt an, welche Kompressionsmethoden der Client akzeptiert. Hier sind es gzip und deflate, was bedeutet, dass der Server die Antwort komprimieren kann, um die Übertragungszeit zu verkürzen. Accept-Charset gibt die akzeptierten Zeichensätze an. Connection keep-alive fordert, dass die TCP-Verbindung nach der Antwort offen bleibt, um weitere Anfragen zu ermöglichen, ohne neue Verbindungen aufbauen zu müssen. Dies verbessert die Effizienz bei mehreren Anfragen. Cache-Control gibt hier an, dass die angeforderte Ressource nicht aus dem Cache geladen werden soll und der Server die aktuellste Version liefern soll. Das Bild zeigt eine HTTP-Antwort, die von einem Webserver an einen Client, beispielsweise an einen Webbrowser, gesendet wurde. Diese erste Zeile zeigt die HTTP-Version und den Statuscode 200, gefolgt von einem Status-Text (OK). Der Statuscode 200 bedeutet, dass die Anfrage erfolgreich war und der Server die angeforderte Ressource bereitstellt. Danach kommt das Datum und die Uhrzeit, zu der die Antwort vom Server generiert wurde. Expires gibt das Ablaufdatum und die Uhrzeit an. Hier scheint es jedoch ein Beispiel für einen ungültigen oder absichtlich veralteten Zeitstempel zu sein, um das Caching zu verhindern. Content-Encoding gibt hier an, dass der Inhalt mit gzip komprimiert wurde. Content-Length 7010 ist die Länge des Antwortkörpers in Bytes. Content-Type beinhaltet den Medientyp des Antwortkörpers und die Zeichencodierung, also hier eine HTML-Seite mit UTF-8-Kodierung. Der eigentliche Inhalt der Antwort beginnt mit dem HTML-Dokument. Dies ist der Teil der Antwort, der vom Webbrowser angezeigt wird. Hier nochmal einige wichtige Felder im Header: Date: Der Zeitpunkt der Anforderung oder Antwort. Content-Type: Der Typ der Daten. Content-Length: Die Länge der Daten in Bytes. Content-Encoding: Die Codierung der Daten und die Komprimierung. Last-Modified: Die letzte Änderung der Daten. Wichtige Felder im HTTP-Request sind: Host: Der Name des Hosts im Request. If-Modified-Since: Fordert nur aktualisierte Version an. Referer: Von welchem Dokument wurde dieses verwiesen? User-Agent: Informationen über den Browser Und abschließend wichtige Felder im HTTP-Response: Server: Information über den Server WWW-Authenticate: verlangt eine Authentifizierung Noch ein paar Details zu den MIME-Typen. Die Multi Purpose Internet Mail Extensions (MIME) definieren den Typ einer Nachricht im Internet. Ein MIME-Typ besteht aus Medientyp (content type) und Subtyp (subtype). Die Syntax lautet: Medientyp / Subtyp. Die Liste der MIME-Typen wird von der Internet Assigned Numbers Authority (IANA) verwaltet, die auch für die IP-Adressenvergabe und das Root Domain Name System (Root-DNS) verantwortlich ist. Hier sehen Sie einige Medientypen mit deren Bedeutung und konkreten Beispielen dazu. In dieser Abbildung sehen Sie die Anfrage eines Clients auf einen HTTP-Server sowie den HTTP-Header der Anfrage. Der Server antwortet mit dem HTTP-Response, der aus dem HTTP-Header und dem HTTP-Body besteht. Der HTTP-Body beinhaltet eine HTML-Datei, die ihrerseits wieder einen HTML-Header und einen HTML-Body besitzt. Der HTML-Body beinhaltet den Content, der im Webbrowser zu lesen ist. Mithilfe der HTTP-Request Methode GET können Parameter an den Server übergeben werden. Dies ist besonders dann sinnvoll, wenn Anfragen auf die gleiche Seite unterscheiden werden sollen: Welche Sprache soll angezeigt werden? Wurde ein Formular auf dieser Seite abgesendet? Die Parameter werden dabei in key-value Paaren hinter die Anfrage, direkt in der URL und für jeden lesbar und änderbar gesetzt. Dabei sind gegebenenfalls Beschränkungen der Länge der URL zu beachten. Das Fragezeichen leitet dabei die HTTP GET-Parameter ein. Das "und" trennt die key-value Paare. Die Idee der key-value Paare kann mit einer HashMap in Java verglichen werden. Im Gegensatz zu GET schickt POST innerhalb des HTTP-Requests unbegrenzte, je nach physischer Ausstattung des eingesetzten Servers, Mengen an Daten zur weiteren Verarbeitung zum Server. Diese Daten werden als Inhalt der Nachricht übertragen und können beispielsweise aus Name-Wert-Paaren bestehen, die aus einem HTML-Formular stammen. In dem HTTP-POST-Request bittet man den Server um die Auswertung dieser Daten, zum Beispiel zur Neuanmeldung an einem System. Dabei können neue Ressourcen auf dem Server entstehen oder bestehende modifiziert werden. POST-Daten werden im Allgemeinen nicht von Browser-Caches zwischengespeichert. Hier sehen Sie einen HTTP-POST-Request, der zwei Parameter im HTTP-Header überträgt. Die Namen der Parameter sind "username" und "pass"; die Werte zu den Parametern stehen hinter dem Gleichheitszeichen. Sie sehen, dass die Parameter zwar nicht für Jedermann in der URL sichtbar sind, sie werden aber im Klartext übertragen. Mit Tools wie Postman kann man solche HTTP-POST-Requests selbst erzeugen und mit Tools wie Wireshark kann man die HTTP-Header problemlos auslesen. Der HTTP-POST-Request hat eine PHP-Datei zum Ziel. Die serverseitig ausgeführte Skriptsprache PHP kann die Parameter aus dem Request herausholen, prüfen und beispielsweise mit Daten aus einer Datenbank des Servers abgleichen. Der Header der Antwort in Form eines HTTP-Responses ist unten dargestellt. In dem Header sieht man, dass der Server einen Cookie zum Client sendet, der den Benutzernamen enthält. Der Client speichert sich dann diesen Cookie im Webbrowser, so dass der Server diesen Benutzer wiedererkennen kann. Hier nochmals sehr deutlich ein paar Hinweise zu HTTP-POST. Ein typischer Anwendungsfall ist es, dass ein HTML-Formular Benutzername und Passwort abfragt. Die beiden Informationen werden dann via POST an den Server übermittelt. Aber Achtung: HTTP-POST-Daten sind nicht sicher, denn es gibt keine Verschlüsselung! Sie werden nur nicht so sehr sichtbar über URL-Parameter (wie beim HTTP-GET) übertragen! Sie können auch nicht „gebookmarked“ werden! Beispielsweise sollte man eine Navigationsauswahl auf eine bestimmte Unterseite immer per HTTP-GET übertragen, damit man eine Referenz auf diese Unterseite auch als Bookmark im Webbrowser ablegen kann. Neben GET und POST gibt es noch weitere HTTP-Request-Methoden: "HEAD" weist den Server an, die gleichen HTTP-Header wie bei GET, nicht jedoch den eigentlichen Dokumentinhalt zu senden. So kann zum Beispiel schnell die Gültigkeit einer Datei im Browser-Cache geprüft werden. "PUT" dient dazu, eine Ressource, zum Beispiel eine Datei, unter Angabe des Ziel-URIs auf einen Webserver hochzuladen. Es können so neue Ressourcen auf dem Server entstehen oder bestehende modifiziert werden. "DELETE" löscht die angegebene Ressource auf dem Server. Heutzutage ist DELETE, ebenso wie PUT, in der Standardkonfiguration von Webservern abgeschaltet. Beides erlangt jedoch mit RESTful Web Services eine neue Bedeutung. "TRACE" liefert die Anfrage so zurück, wie der Server sie empfangen hat. So kann überprüft werden, ob und wie die Anfrage auf dem Weg zum Server verändert worden ist und es ist sinnvoll für das Debugging von Verbindungen. "OPTIONS" liefert eine Liste der vom Server unterstützten Methoden und Features. "CONNECT" wird von Proxyservern implementiert, die in der Lage sind, SSL-Tunnel zur Verfügung zu stellen. Kommen wir nun zu den wichtigsten HTTP-Statuscodes von Antworten: Hunderter-Codes sind zur reinen Information wie: Die Bearbeitung der Anfrage dauert noch an. Zweihunderter-Codes sind generell Erfolgsmeldungen. Dreihunderter-Codes zeigen Weiterleitungen an. Um eine erfolgreiche Bearbeitung der Anfrage sicherzustellen, sind weitere Schritte seitens des Clients erforderlich. Der Client muss also eine weitere Anfrage stellen, die wohl ein anderes Ziel hat. Vierhunderter-Codes sind Client-Fehler. Sie sind nicht klar von den so genannten Server-Fehlern abzugrenzen. Die Ursache des Scheiterns der Anfrage liegt jedoch eher im Verantwortungsbereich des Clients. Fünfhunderter-Codes sind Server-Fehler. Die Ursache des Scheiterns der Anfrage liegt eher im Verantwortungsbereich des Servers. Hier sehen Sie einen Ausschnitt einer htaccess-Datei, die sich auf einem Apache-Webserver befindet. Über Error-Document können Sie fertige HTML-Seiten bestimmten Fehlercodes zuordnen. Dadurch wird immer diese HTML-Seite aufgerufen, wenn so ein Fehler auftritt. Mit Redirect können Sie anweisen, dass eine Anfrage, hier auf eine veraltete PHP-Datei, mit einer 301-Fehlermeldung beantwortet wird. In der HTTP-Antwort wird dann die aktuelle HTML-Datei angegeben, die die PHP-Datei auf dem Server ersetzte. Auf diese Weise verhindern Sie tote Links und leiten Verweise auf nicht mehr existierende Linkziele auf gültige Seiten um. Zum Abschluss noch ein paar weit verbreitete Statuscodes, die man kennen sollte: 301 "Moved Permanently" bedeutet: Die angeforderte Ressource steht ab sofort unter der im "Location"-Header-Feld angegebenen Adresse bereit (auch Redirect genannt). Die alte Adresse ist nicht länger gültig. 401 "Unauthorized" bedeutet: Die Anfrage kann nicht ohne gültige Authentifizierung durchgeführt werden. Wie die Authentifizierung durchgeführt werden soll, wird im Authenticate-Headerfeld der Antwort übermittelt. 403 "Forbidden" bedeutet: Die Anfrage wurde mangels Berechtigung des Clients nicht durchgeführt. Diese Entscheidung wurde, anders als im Fall des Statuscodes 401, unabhängig von Authentifizierungsinformationen getroffen, auch etwa wenn eine als HTTPS konfigurierte URL nur mit HTTP aufgerufen wurde. 404 "Not Found" bedeutet: Die angeforderte Ressource wurde nicht gefunden. Dieser Statuscode kann ebenfalls verwendet werden, um eine Anfrage ohne näheren Grund abzuweisen. Links, welche auf solche Fehlerseiten verweisen, werden auch als tote Links bezeichnet. 500 "Internal Server Error" bedeutet: Dies ist ein Sammel-Statuscode für unerwartete Serverfehler.